/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/

#include "stdafx.h"
#include <pgl/core/PGLAxe.h>
#include <pgl/core/PGLArchive.h>
#include <pgl/core/PGLAxe2DPropPage.h>
#include <pgl/core/PGLSolidBrush.h>
#include "../IGfx/GDILeak.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

PGL_IMPLEMENT_DYNCREATE(CPGLAxe2D, CPGLObject);

void CPGLAxe2D::SerializeXML(CPGLArchive& ar)
{
	static TCHAR szTag[] = _T("CPGLAxe2D");

	markup::CMarkupArchive& xml = *((markup::CMarkupArchive*)ar.GetMarkup());
	if(ar.IsStoring())
	{
		xml.AddChildElem(szTag);
		xml.AddChildAttrib(_T("Name"),GetName());
		xml.IntoElem();

		CPGLObject::SerializeXML(ar);

			//////////////////////////////////////////////////////
			// labels
			xml.AddChildElem(_T("Labels"));
			xml.IntoElem();
				xml.AddChildElem(_T("Bottom"));
				xml.IntoElem();
					m_pLabels[0].SerializeXML(ar);
				xml.OutOfElem();
	
				xml.AddChildElem(_T("Left"));
				xml.IntoElem();
					m_pLabels[1].SerializeXML(ar);
				xml.OutOfElem();
	
				xml.AddChildElem(_T("Right"));
				xml.IntoElem();
					m_pLabels[2].SerializeXML(ar);
				xml.OutOfElem();
	
				xml.AddChildElem(_T("Top"));
				xml.IntoElem();
					m_pLabels[3].SerializeXML(ar);
				xml.OutOfElem();
			xml.OutOfElem();

			//////////////////////////////////////////////////////
			// Numbering
			xml.AddChildElem(_T("Numbering"));
			xml.IntoElem();
                xml.AddChildElemEx(_T("MaxSignficativeNumber"),m_max_significative_number);
                xml.AddChildElemEx(_T("DecimalSignficativeNumber"),m_decimal_significative_number);
				xml.AddChildElem(_T("Bottom"));
				xml.IntoElem();
					m_pNumbers[0].SerializeXML(ar);
					xml.AddChildElemEx(_T("ExpLimit"),m_pNumberExpLimits[0]);
					xml.AddChildElemEx(_T("Pos"),m_pNumberPos[0]);
				xml.OutOfElem();
	
				xml.AddChildElem(_T("Left"));
				xml.IntoElem();
					m_pNumbers[1].SerializeXML(ar);
					xml.AddChildElemEx(_T("ExpLimit"),m_pNumberExpLimits[1]);
					xml.AddChildElemEx(_T("Pos"),m_pNumberPos[1]);
				xml.OutOfElem();
	
				xml.AddChildElem(_T("Right"));
				xml.IntoElem();
					m_pNumbers[2].SerializeXML(ar);
					xml.AddChildElemEx(_T("ExpLimit"),m_pNumberExpLimits[2]);
					xml.AddChildElemEx(_T("Pos"),m_pNumberPos[2]);
				xml.OutOfElem();
	
				xml.AddChildElem(_T("Top"));
				xml.IntoElem();
					m_pNumbers[3].SerializeXML(ar);
					xml.AddChildElemEx(_T("ExpLimit"),m_pNumberExpLimits[3]);
					xml.AddChildElemEx(_T("Pos"),m_pNumberPos[3]);
				xml.OutOfElem();
			xml.OutOfElem();
			

			//////////////////////////////////////////////////////
			// Grids
			xml.AddChildElem(_T("Grid"));
			xml.IntoElem();
				xml.AddChildElem(_T("Ver"));
				xml.IntoElem();
					m_lVerGrid.SerializeXML(ar);
				xml.OutOfElem();
				xml.AddChildElem(_T("Hor"));
				xml.IntoElem();
					m_lHorGrid.SerializeXML(ar);
				xml.OutOfElem();
			xml.OutOfElem();

			///////////////////////////////////////////////////////////
			// BoxTicks
			xml.AddChildElem(_T("BoxTicks"));
			xml.IntoElem();
				m_lBoxTicks.SerializeXML(ar);
				xml.AddChildElem(_T("Vis"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("Left"), m_rBorderLineVis.left);
					xml.AddChildElemEx(_T("Right"), m_rBorderLineVis.right);
					xml.AddChildElemEx(_T("Top"), m_rBorderLineVis.top);
					xml.AddChildElemEx(_T("Bottom"), m_rBorderLineVis.bottom);
				xml.OutOfElem();
			xml.OutOfElem();

			///////////////////////////////////////////////////////
			// Time labelling
			xml.AddChildElem(_T("TimeLabel"));
			xml.IntoElem();
				xml.AddChildElemEx(_T("Enabled"),m_bTimeLabel);
				xml.AddChildElemEx(_T("Origin"),m_tTimeLabelOrig);
				xml.AddChildElemEx(_T("Unit"),m_tsDt);
				xml.AddChildElem(_T("Format"),m_sTimeLabel);
			xml.OutOfElem();


			/////////////////////////////////////////////////////////////
			// Steps and ticks
			xml.AddChildElem(_T("Steps"));
			xml.IntoElem();
				xml.AddChildElemEx(_T("AxisSquare"), m_bAxisSquare);
				xml.AddChildElem(_T("Horizontal"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("Auto"), (bool)m_pAutoSteps[0]);
					xml.AddChildElemEx(_T("Min"), m_pStarts[0]);
					xml.AddChildElemEx(_T("Max"), m_pEnds[0]);
					xml.AddChildElemEx(_T("Step"), m_pSteps[0]);
					xml.AddChildElemEx(_T("Log"), (bool)m_pLogAxis[0]);
					xml.AddChildElemEx(_T("NSteps"), (bool)m_pNSteps[0]);
				xml.OutOfElem();
				xml.AddChildElem(_T("Vertical"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("Auto"), (bool)m_pAutoSteps[1]);
					xml.AddChildElemEx(_T("Min"), m_pStarts[1]);
					xml.AddChildElemEx(_T("Max"), m_pEnds[1]);
					xml.AddChildElemEx(_T("Step"), m_pSteps[1]);
					xml.AddChildElemEx(_T("Log"), (bool)m_pLogAxis[1]);
					xml.AddChildElemEx(_T("NSteps"), (bool)m_pNSteps[1]);
			    xml.OutOfElem();
			xml.OutOfElem();

			///////////////////////////////////////////////////////////////////
			/// Ticks
			xml.AddChildElem(_T("Ticks"));
			xml.IntoElem();
				xml.AddChildElem(_T("Left"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("MainSize"), m_pMainTicksSize[ETickLeft]);
					xml.AddChildElemEx(_T("SecondSize"), m_pSecondTicksSize[ETickLeft]);
					xml.AddChildElemEx(_T("SecondNb"), m_pSecondTicksNb[ETickLeft]);
					m_pSecondTicksNb[ETickLeft] = __max( 1, m_pSecondTicksNb[ETickLeft]);
				xml.OutOfElem();
				xml.AddChildElem(_T("Right"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("MainSize"), m_pMainTicksSize[ETickRight]);
					xml.AddChildElemEx(_T("SecondSize"), m_pSecondTicksSize[ETickRight]);
					xml.AddChildElemEx(_T("SecondNb"), m_pSecondTicksNb[ETickRight]);
					m_pSecondTicksNb[ETickRight] = __max( 1, m_pSecondTicksNb[ETickRight]);
				xml.OutOfElem();
				xml.AddChildElem(_T("Bottom"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("MainSize"), m_pMainTicksSize[ETickBottom]);
					xml.AddChildElemEx(_T("SecondSize"), m_pSecondTicksSize[ETickBottom]);
					xml.AddChildElemEx(_T("SecondNb"), m_pSecondTicksNb[ETickBottom]);
					m_pSecondTicksNb[ETickBottom] = __max( 1, m_pSecondTicksNb[ETickBottom]);
				xml.OutOfElem();
				xml.AddChildElem(_T("Top"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("MainSize"), m_pMainTicksSize[ETickTop]);
					xml.AddChildElemEx(_T("SecondSize"), m_pSecondTicksSize[ETickTop]);
					xml.AddChildElemEx(_T("SecondNb"), m_pSecondTicksNb[ETickTop]);
					m_pSecondTicksNb[ETickTop] = __max( 1, m_pSecondTicksNb[ETickTop]);
				xml.OutOfElem();
			xml.OutOfElem();
				

			///////////////////////////////////////////////////////////////////
			/// Borders
			xml.AddChildElem(_T("Borders"));
			xml.IntoElem();
				xml.AddChildElem(_T("Left"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("Auto"),m_rAutoBorders.left);
					xml.AddChildElemEx(_T("Size"),m_rBorders.left);
				xml.OutOfElem();
				xml.AddChildElem(_T("Bottom"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("Auto"),m_rAutoBorders.bottom);
					xml.AddChildElemEx(_T("Size"),m_rBorders.bottom);
				xml.OutOfElem();
				xml.AddChildElem(_T("Right"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("Auto"),m_rAutoBorders.right);
					xml.AddChildElemEx(_T("Size"),m_rBorders.right);
				xml.OutOfElem();
				xml.AddChildElem(_T("Top"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("Auto"),m_rAutoBorders.top);
					xml.AddChildElemEx(_T("Size"),m_rBorders.top);
				xml.OutOfElem();
			xml.OutOfElem();

		// closing axis
		xml.OutOfElem();
	}
	else
	{
		if  (!xml.FindChildElem(szTag))
				return;

		xml.IntoElem();
			// loading base class
			CPGLObject::SerializeXML(ar);

			// laoding labels
			xml.ResetChildPos();
			if(xml.FindChildElem(_T("Labels")) )
			{
				xml.IntoElem();
				// loading bottom label
				if (xml.FindChildElem(_T("Bottom")) )
				{
					xml.IntoElem();		
						m_pLabels[0].SerializeXML(ar);					
					xml.OutOfElem();	
				}

				// loading left label
				xml.ResetChildPos();
				if (xml.FindChildElem(_T("Left")) )
				{
					xml.IntoElem();		
						m_pLabels[1].SerializeXML(ar);					
					xml.OutOfElem();	
				}

				// loading right label
				xml.ResetChildPos();
				if (xml.FindChildElem(_T("Right")) )
				{
					xml.IntoElem();		
						m_pLabels[2].SerializeXML(ar);					
					xml.OutOfElem();	
				}

				// loading top label
				xml.ResetChildPos();
				if (xml.FindChildElem(_T("Top")) )
				{
					xml.IntoElem();		
						m_pLabels[3].SerializeXML(ar);					
					xml.OutOfElem();	
				}

				xml.OutOfElem();
			}

			// laoding numbers
			xml.ResetChildPos();
			if(xml.FindChildElem(_T("Numbering")) )
			{
				xml.IntoElem();

                xml.FindGetChildData(_T("MaxSignficativeNumber"),m_max_significative_number);
                xml.FindGetChildData(_T("DecimalSignficativeNumber"),m_decimal_significative_number);

				// loading bottom number
				if (xml.FindChildElem(_T("Bottom")) )
				{
					xml.IntoElem();		
						m_pNumbers[0].SerializeXML(ar);
						xml.FindGetChildData(_T("ExpLimit"),m_pNumberExpLimits[0]);
						xml.FindGetChildData(_T("Pos"), m_pNumberPos[0]);
					xml.OutOfElem();	
				}

				// loading left label
				xml.ResetChildPos();
				if (xml.FindChildElem(_T("Left")) )
				{
					xml.IntoElem();		
						m_pNumbers[1].SerializeXML(ar);					
						xml.FindGetChildData(_T("ExpLimit"),m_pNumberExpLimits[1]);
						xml.FindGetChildData(_T("Pos"), m_pNumberPos[1]);
					xml.OutOfElem();	
				}

				// loading right label
				xml.ResetChildPos();
				if (xml.FindChildElem(_T("Right")) )
				{
					xml.IntoElem();		
						m_pNumbers[2].SerializeXML(ar);					
						xml.ResetChildPos();
						xml.FindGetChildData(_T("ExpLimit"),m_pNumberExpLimits[2]);
						xml.FindGetChildData(_T("Pos"), m_pNumberPos[2]);
					xml.OutOfElem();	
				}

				// loading top label
				xml.ResetChildPos();
				if (xml.FindChildElem(_T("Top")) )
				{
					xml.IntoElem();		
						m_pNumbers[3].SerializeXML(ar);					
						xml.FindGetChildData(_T("ExpLimit"),m_pNumberExpLimits[3]);
						xml.FindGetChildData(_T("Pos"), m_pNumberPos[3]);
					xml.OutOfElem();	
				}

				xml.OutOfElem();
			}
			
			//////////////////////////////////////////////////////
			// Grids
			xml.ResetChildPos();
			if (xml.FindChildElem(_T("Grid")))
			{
				xml.IntoElem();

					if(xml.FindChildElem(_T("Ver")) )
					{
						xml.IntoElem();
							m_lVerGrid.SerializeXML(ar);
						xml.OutOfElem();
					}

					xml.ResetChildPos();
					if(xml.FindChildElem(_T("Hor")) )
					{
						xml.IntoElem();
							m_lHorGrid.SerializeXML(ar);
						xml.OutOfElem();
					}
				xml.OutOfElem();
			}

			xml.ResetChildPos();
			if (xml.FindChildElem(_T("BoxTicks")))
			{
				xml.IntoElem();
					m_lBoxTicks.SerializeXML(ar);

					xml.ResetChildPos();
					if (xml.FindChildElem(_T("Vis")))
					{
						xml.IntoElem();
							xml.FindGetChildData(_T("Left"), m_rBorderLineVis.left);
							xml.FindGetChildData(_T("Right"), m_rBorderLineVis.right);
							xml.FindGetChildData(_T("Top"), m_rBorderLineVis.top);
							xml.FindGetChildData(_T("Bottom"), m_rBorderLineVis.bottom);
						xml.OutOfElem();
					}
				xml.OutOfElem();
			}

			///////////////////////////////////////////////////////
			// Time labelling
			xml.ResetChildPos();
			if (xml.FindChildElem(_T("TimeLabel")))
			{
				xml.IntoElem();
					xml.FindGetChildData(_T("Enabled"), m_bTimeLabel);
					xml.FindGetChildData(_T("Origin"),m_tTimeLabelOrig);
					xml.FindGetChildData(_T("Unit"),m_tsDt);
					xml.FindGetChildData(_T("Format"),m_sTimeLabel);
				xml.OutOfElem();
			}

			/////////////////////////////////////////////////////////////
			// Steps and ticks
			xml.ResetChildPos();
			if(xml.FindChildElem(_T("Steps")))
			{
				xml.IntoElem();
					xml.FindGetChildData(_T("AxisSquare"), m_bAxisSquare);

					xml.ResetChildPos();
					if(xml.FindChildElem(_T("Horizontal")) )
					{
						xml.IntoElem();
							xml.FindGetChildData(_T("Auto"),m_pAutoSteps[0]);
							xml.FindGetChildData(_T("Min"),m_pStarts[0]);
							xml.FindGetChildData(_T("Max"),m_pEnds[0]);
							xml.FindGetChildData(_T("Step"),m_pSteps[0]);
							xml.FindGetChildData(_T("Log"),m_pLogAxis[0]);
							xml.FindGetChildData(_T("NSteps"),m_pNSteps[0]);
						xml.OutOfElem();
					}

					if(xml.FindChildElem(_T("Vertical")) )
					{
						xml.IntoElem();
							xml.FindGetChildData(_T("Auto"),m_pAutoSteps[1]);
							xml.FindGetChildData(_T("Min"),m_pStarts[1]);
							xml.FindGetChildData(_T("Max"),m_pEnds[1]);
							xml.FindGetChildData(_T("Step"),m_pSteps[1]);
							xml.FindGetChildData(_T("Log"),m_pLogAxis[1]);
							xml.FindGetChildData(_T("NSteps"),m_pNSteps[1]);
						xml.OutOfElem();
					}
				// steps
				xml.OutOfElem();
			}

			/////////////////////////////////////////////////////////////////////////////////:
			// Ticks
			if (xml.FindChildElem(_T("Ticks")))
			{
				xml.IntoElem();
					if(xml.FindChildElem(_T("Left")))
					{
						xml.IntoElem();
							xml.FindGetChildData(_T("MainSize"), m_pMainTicksSize[ETickLeft]);
							xml.FindGetChildData(_T("SecondSize"), m_pSecondTicksSize[ETickLeft]);
							xml.FindGetChildData(_T("SecondNb"), m_pSecondTicksNb[ETickLeft]);
						xml.OutOfElem();
					}

					xml.ResetChildPos();
					if(xml.FindChildElem(_T("Right")))
					{
						xml.IntoElem();
							xml.FindGetChildData(_T("MainSize"), m_pMainTicksSize[ETickRight]);
							xml.FindGetChildData(_T("SecondSize"), m_pSecondTicksSize[ETickRight]);
							xml.FindGetChildData(_T("SecondNb"), m_pSecondTicksNb[ETickRight]);
						xml.OutOfElem();
					}

					xml.ResetChildPos();
					if(xml.FindChildElem(_T("Bottom")))
					{
						xml.IntoElem();
							xml.FindGetChildData(_T("MainSize"), m_pMainTicksSize[ETickBottom]);
							xml.FindGetChildData(_T("SecondSize"), m_pSecondTicksSize[ETickBottom]);
							xml.FindGetChildData(_T("SecondNb"), m_pSecondTicksNb[ETickBottom]);
						xml.OutOfElem();
					}

					xml.ResetChildPos();
					if(xml.FindChildElem(_T("Top")))
					{
						xml.IntoElem();
							xml.FindGetChildData(_T("MainSize"), m_pMainTicksSize[ETickTop]);
							xml.FindGetChildData(_T("SecondSize"), m_pSecondTicksSize[ETickTop]);
							xml.FindGetChildData(_T("SecondNb"), m_pSecondTicksNb[ETickTop]);
						xml.OutOfElem();
					}
				xml.OutOfElem();
			}
			/////////////////////////////////////////////////////////////////////////////////:
			// Borders
			if(xml.FindChildElem(_T("Borders")))
			{
				xml.IntoElem();
					if(xml.FindChildElem(_T("Left")))
					{
						xml.IntoElem();
							xml.FindGetChildData(_T("Auto"),m_rAutoBorders.left);
							xml.FindGetChildData(_T("Size"),m_rBorders.left);
						xml.OutOfElem();
					}

					xml.ResetChildPos();
					if(xml.FindChildElem(_T("Bottom")))
					{
						xml.IntoElem();
							xml.FindGetChildData(_T("Auto"),m_rAutoBorders.bottom);
							xml.FindGetChildData(_T("Size"),m_rBorders.bottom);
						xml.OutOfElem();
					}

					xml.ResetChildPos();
					if(xml.FindChildElem(_T("Right")))
					{
						xml.IntoElem();
							xml.FindGetChildData(_T("Auto"),m_rAutoBorders.right);
							xml.FindGetChildData(_T("Size"),m_rBorders.right);
						xml.OutOfElem();
					}

					xml.ResetChildPos();
					if(xml.FindChildElem(_T("Top")))
					{
						xml.IntoElem();
							xml.FindGetChildData(_T("Auto"),m_rAutoBorders.top);
							xml.FindGetChildData(_T("Size"),m_rBorders.top);
						xml.OutOfElem();
					}

				xml.OutOfElem();

				////////////////////////////////////////////////////////////////////////::
				// Frame
				
			}

		// the end
		xml.OutOfElem();

		// need update
		NeedUpdateExtent();
	}
}

#ifdef _DEBUG
void CPGLAxe2D::Dump( CDumpContext& dc ) const
{
    // call base class function first
    CPGLObject::Dump( dc );

	// now dumping..
	dc << _T("--- CPGLAxe2D ID ") << GetID() <<_T(" --- ")<< "\n";
}

void CPGLAxe2D::AssertValid() const
{
    // call inherited AssertValid first
    CPGLObject::AssertValid();

	ASSERT_VALID(m_pView);
	for (int i=0;i<4;i++)
	{
		m_pLabels[i].AssertValid();
		m_pNumbers[i].AssertValid();
	}
} 
#endif

CPGLAxe2D::CPGLAxe2D(CPGLView2D* pView)
: CPGLObject(), 
m_pView(pView), 
m_bAxisSquare(false), 
m_bTimeLabel(false),
m_tTimeLabelOrig(COleDateTime::GetCurrentTime()), 
m_tsDt(COleDateTimeSpan(0,1,0,0)),
m_sTimeLabel(_T("%H")), 
m_rBorderLineVis(true, true, true, true), 
m_rBorders(CPGLRectD(40,40,40,40)),
m_decimal_significative_number(1),
m_max_significative_number(3)
{
	using namespace gfxinterface;

	size_t i;
	SetColor(0.0,0.0,0.0,1.0f);

	for (i=0;i<2;i++)
	{
		m_pStarts[i]=0.0;
		m_pEnds[i]=1.0;
		m_pAutoSteps[i]=true;
		m_pLogAxis[i]=false;
		m_pNSteps[i]=10;
		GenerateSteps((EAxis)i);
	}

	SetName(_T("Axis"));

	///////////////////////////////////////////////////
	// Grids
	m_lHorGrid.SetName(_T("Horizontal Grid"));
	m_lVerGrid.SetName(_T("Vertical Grid"));
	m_lHorGrid.SetColor(0,0,0);
	m_lHorGrid.SetLineWidth(1);
	m_lVerGrid.SetColor(0,0,0);
	m_lVerGrid.SetLineWidth(1);
	m_lHorGrid.SetDashPattern(PGL_LINE_POINTPOINT);
	m_lVerGrid.SetDashPattern(PGL_LINE_POINTPOINT);

	m_lBoxTicks.SetName(_T("Box and ticks"));
	m_lBoxTicks.SetColor(0,0,0);
	m_lBoxTicks.SetLineWidth(1.8f);

	///////////////////////////////////////////////////
	/// Labels
	m_pLabels[ELabelBottom].SetString(_T("Bottom Label"));
	m_pLabels[ELabelBottom].SetName(_T("Bottom label"));
	m_pLabels[ELabelBottom].SetAlign(TextAlignmentCenter);
	m_pLabels[ELabelBottom].GetPosition().SetPosition(0.5,0,CPGLCoord2D::Coord2DNorm); 

	m_pLabels[ELabelLeft].SetString(_T("Left Label"));
	m_pLabels[ELabelLeft].SetName(_T("Left label"));
	m_pLabels[ELabelLeft].SetAngle(90);
	m_pLabels[ELabelLeft].SetAlign(TextAlignmentCenter);
	m_pLabels[ELabelLeft].GetPosition().SetPosition(0,0.5,CPGLCoord2D::Coord2DNorm); 

	m_pLabels[ELabelRight].SetString(_T("Right Label"));
	m_pLabels[ELabelRight].SetName(_T("Right label"));
	m_pLabels[ELabelRight].SetAngle(90);
	m_pLabels[ELabelRight].SetAlign(TextAlignmentCenter);
	m_pLabels[ELabelRight].Hide();
	m_pLabels[ELabelRight].GetPosition().SetPosition(1,0.5,CPGLCoord2D::Coord2DNorm); 

	m_pLabels[ELabelTop].SetString(_T("Title"));
	m_pLabels[ELabelTop].SetName(_T("Top label"));
	m_pLabels[ELabelTop].SetAlign(TextAlignmentCenter);
	m_pLabels[ELabelTop].GetPosition().SetPosition(0.5,1,CPGLCoord2D::Coord2DNorm); 

	/////////////////////////////////////////////////////
	// numbering
	m_pNumbers[ENumberingBottom].SetString(_T("0.001"));
	m_pNumbers[ENumberingBottom].SetName(_T("Bottom numbering"));
	m_pNumbers[ENumberingBottom].SetAlign(TextAlignmentCenter);
	m_pNumbers[ENumberingBottom].SetDescription(_T("%.3g"));
	m_pNumberExpLimits[ENumberingBottom]=3;
	m_pNumberPos[ENumberingBottom]=0;

	m_pNumbers[ENumberingLeft].SetString(_T("0.001"));
	m_pNumbers[ENumberingLeft].SetName(_T("Left Numbering"));
	m_pNumbers[ENumberingLeft].SetAlign(TextAlignmentRight);
	m_pNumbers[ENumberingLeft].SetDescription(_T("%.3g"));
	m_pNumberExpLimits[ENumberingLeft]=6; 
	m_pNumberPos[ENumberingLeft]=0;

	m_pNumbers[ENumberingRight].SetString(_T("0.001"));
	m_pNumbers[ENumberingRight].SetName(_T("Right Numbering"));
	m_pNumbers[ENumberingRight].SetAlign(TextAlignmentLeft);
	m_pNumbers[ENumberingRight].SetDescription(_T("%.3g"));
	m_pNumbers[ENumberingRight].Hide();
	m_pNumberExpLimits[ENumberingRight]=3;
	m_pNumberPos[ENumberingRight]=1;

	m_pNumbers[ENumberingTop].SetString(_T("0.001"));
	m_pNumbers[ENumberingTop].SetName(_T("Top Numbering"));
	m_pNumbers[ENumberingTop].SetAlign(TextAlignmentCenter);
	m_pNumbers[ENumberingTop].SetDescription(_T("%.3g"));
	m_pNumbers[ENumberingTop].Hide();
	m_pNumberExpLimits[ENumberingTop]=3;
	m_pNumberPos[ENumberingTop]=1;

	///////////////////////////////////////////////////////////////
	// Ticks
	for (i=0;i<4;i++)
	{
		m_pMainTicksSize[i]=8;
		m_pSecondTicksSize[i]=6;
		m_pSecondTicksNb[i]=1;
	}

	//////////////////////////////////////////////////////////////
	/// Borders
	m_rAutoBorders.left=m_rAutoBorders.right=m_rAutoBorders.bottom=m_rAutoBorders.top=true;
	m_rBorders.left=m_rBorders.bottom=m_rBorders.top=40;
	m_rBorders.right=20;

	CPGLSolidBrushPtr brush(new CPGLSolidBrush()); 
	SetBrush(brush);

	LoadBitmap(IDB_PGL_AXE2D_BITMAP);
}

CPGLAxe2D& CPGLAxe2D::operator=(const CPGLAxe2D& a)
{
   
	int i;
	// prevent self-assignement
	if (&a != this)
	{
		// invoke CPGLObject copy assignement operator
		this->CPGLObject::operator =(a);

		m_bAxisSquare = a.m_bAxisSquare;

		// copy the operand
		for (i=0;i<4;i++)
		{
			m_pLabels[i]=a.m_pLabels[i];
			m_pNumbers[i]=a.m_pNumbers[i];
			m_pNumberPos[i]=a.m_pNumberPos[i];
			m_pNumberExpLimits[i]=a.m_pNumberExpLimits[i];
			m_pMainTicksSize[i]=a.m_pMainTicksSize[i];
			m_pSecondTicksSize[i]=a.m_pSecondTicksSize[i];
			m_pSecondTicksNb[i]=a.m_pSecondTicksNb[i];
		}

		for (i=0;i<2;i++)
		{
			m_pStarts[i]=a.m_pStarts[i];
			m_pEnds[i]=a.m_pEnds[i];
			m_pSteps[i]=a.m_pSteps[i];
			m_pAutoSteps[i]=a.m_pAutoSteps[i];
			m_pLogAxis[i]=a.m_pLogAxis[i];
			m_pNSteps[i]=a.m_pNSteps[i];
		}

		m_lHorGrid = a.m_lHorGrid;
		m_lVerGrid = a.m_lVerGrid;
		m_lBoxTicks = a.m_lBoxTicks;

		m_rBorderLineVis = a.m_rBorderLineVis;
		m_rBorders=a.m_rBorders;
		m_rAutoBorders=a.m_rAutoBorders;
		m_pView=a.m_pView;
		m_bTimeLabel = a.m_bTimeLabel;
		m_tTimeLabelOrig = a.m_tTimeLabelOrig;
		m_tsDt = a.m_tsDt;
		m_sTimeLabel = a.m_sTimeLabel;
        m_max_significative_number = a.m_max_significative_number;
        m_decimal_significative_number = a.m_decimal_significative_number;
	}
	return *this;
}

	/// destructor
CPGLAxe2D::~CPGLAxe2D()
{
};

void CPGLAxe2D::PlotGfx(gfxinterface::CGfxInterface& gfx)
{
	using namespace gfxinterface;

	if (!IsVisible())
		return;


	// commentary
	GFX_ADDCOMMENT(gfx,"--- CPGLAxe2D ---");	

	// calling base class function
	CPGLObject::PlotGfx(gfx);

	// drawing inside
	if ( IsInLayer(gfx.GetLayer()) && GetFillBrush() )
	{
		CPGLRectD rBox( m_pStarts[0], m_pStarts[1], m_pEnds[0], m_pEnds[1]);
		GetFillBrush()->SetBBox(rBox);
		GetFillBrush()->MakeCurrentFill(gfx);
		gfx.DrawRect(m_pStarts[0], m_pStarts[1], m_pEnds[0], m_pEnds[1], RectTypeFilled | RectTypeNoContour);
	}

	// line of axe
	DrawLinesGfx(gfx);

	// x grid
	if (m_lVerGrid.IsVisible() && m_lVerGrid.IsInLayer(gfx.GetLayer()))
		DrawGridGfx(AxisVertical,gfx);
	// y grid
	if (m_lHorGrid.IsVisible() && m_lHorGrid.IsInLayer(gfx.GetLayer()))
		DrawGridGfx(AxisHorizontal,gfx);

	// draw numbering
	DrawNumbersGfx(gfx);
}

void CPGLAxe2D::SetLimits(int iaxe, double _start, double _end,gfxinterface::CGfxInterface& gfx)
{
	CPGLRectD rect;
	switch(iaxe)
	{
	case 0:
		rect.left = _start;
		rect.right = _end;
		rect.bottom = m_pStarts[1];
		rect.top = m_pEnds[1];
		break;
	case 1:
		rect.left = m_pStarts[0];
		rect.right = m_pEnds[0];
		rect.bottom = _start;
		rect.top = _end;
		break;
	}

	SetLimits(rect, gfx);
}

void CPGLAxe2D::SetLimits(const CPGLRectD& rLimits,gfxinterface::CGfxInterface& gfx)
{

	CPGLRectD rLimitsTemp = rLimits;
	// checking non empty data...
	if (rLimitsTemp.IsWidthEmpty())
	{
		rLimitsTemp.left-=0.5;
		rLimitsTemp.right+=0.5;
	}
	if (rLimitsTemp.IsHeightEmpty())
	{
		rLimitsTemp.bottom-=0.5;
		rLimitsTemp.top+=0.5;
	}

	// setting values
	m_pStarts[0] = rLimitsTemp.left;
	m_pStarts[1] = rLimitsTemp.bottom;
	m_pEnds[0] = rLimitsTemp.right;
	m_pEnds[1] = rLimitsTemp.top;

	// generating m_pStgfx...
	if (m_pAutoSteps[AxisHorizontal])
		GenerateSteps(AxisHorizontal);
	if (m_pAutoSteps[AxisVertical])
		GenerateSteps(AxisVertical);

	// axis equal case
	if (m_bAxisSquare)
	{
		// taking minimum and maximum...
		double maxwh = __max(m_pEnds[0]-m_pStarts[0], m_pEnds[1] - m_pStarts[1]);
		m_pEnds[0] = m_pStarts[0] + maxwh;
		m_pEnds[1] = m_pStarts[1] + maxwh;
	}

	// repositioning label
	UpdateLabels(gfx);
}			

void CPGLAxe2D::GetLimits(CPGLRectD& rLimits)
{
	rLimits.left=m_pStarts[0];
	rLimits.right=m_pEnds[0];
	rLimits.bottom=m_pStarts[1];
	rLimits.top=m_pEnds[1];
}


void CPGLAxe2D::GenerateSteps(EAxis iaxe)
{
	ASSERT(iaxe >= 0 && iaxe <= 1);

	double dStart=m_pStarts[iaxe];
	double dEnd=m_pEnds[iaxe];

	int numberOfTicks = static_cast<int>(m_pNSteps[iaxe]); // TODO: Should be computed so that no overlap exists
	int bases[]= {1,5,2}; // Tick bases selection
	int currentBase;
	int n;
	double intervalSize, upperBound, lowerBound;
    int nIntervals,nMaxIntervals;
    double the_intervalsize=0.1;

	// Vertical axis ticks
	if (algotools::IsEqual(dStart,dEnd)) // Flat plot
	{
		dEnd+=0.5;
		dStart-=0.5;
	}
		
	int exponentYmax;
	double mantissaYmax;
	double ip_start,ip_end;

	
	exponentYmax = static_cast<int>(
		floor( __max( log10(fabs(dStart)), log10(fabs(dEnd)) ) )
		);
    mantissaYmax = dEnd/pow(10.0,exponentYmax);
	

	// now check if numbers can be cleaned...
	// make it pretty
    double significative_numbers= std::min(
        (double)m_max_significative_number, 
        fabs((double)exponentYmax)+m_decimal_significative_number
        );

	double expo = pow(10.0,  significative_numbers);
	double start_norm = fabs(dStart) * expo;
	double end_norm = fabs(dEnd) * expo;
	double mant_norm = fabs(mantissaYmax) * expo;

	// trunc ends
    dStart = ip_start = floor(_copysign(start_norm,dStart));
    dEnd = ip_end = ceil(_copysign(end_norm,dEnd));

	mantissaYmax=ceil(mant_norm);

	nMaxIntervals=0;
	for (int k = 0; k <sizeof(bases)/sizeof(bases[0]); ++k)
	{
        // Loop initialisation
        currentBase = bases[k];
        n = 4; // This value only allows results smaller than about 1000 = 10^n
		
		
        do // Tick vector length reduction 
        {
			--n;
			intervalSize = currentBase*pow(10.0, exponentYmax-n);

 			upperBound = static_cast<int>(
                ceil(mantissaYmax*pow(10.0,n)/currentBase)
                )*intervalSize;

			nIntervals = static_cast<int>(
                ceil((upperBound-dStart)/intervalSize)
                );
			lowerBound = upperBound - nIntervals*intervalSize;
        }
        while ((nIntervals+1) > numberOfTicks);
        
        if (nIntervals > nMaxIntervals)
        {
			nMaxIntervals=nIntervals;
			ip_start=ip_start=lowerBound;
			ip_end=upperBound;
            the_intervalsize = intervalSize;
        }
	}

	// trunc ends
    if (dStart<0)
        dStart = floor(ip_start)/expo;
    else
        dStart = ceil(ip_start)/expo;

    if (dEnd<0)
        dEnd = floor(ip_end)/expo;
    else
        dEnd = ceil(ip_end)/expo;

    m_pStarts[iaxe]=dStart;
    m_pEnds[iaxe]=dEnd;
    m_pSteps[iaxe] = the_intervalsize / expo;

	if (
        algotools::IsGreaterEqual(m_pStarts[iaxe],m_pEnds[iaxe])
    ) // Flat plot
	{
		m_pStarts[iaxe]=dStart-0.5;
		m_pEnds[iaxe]=dEnd+0.5;
		m_pSteps[iaxe]=0.1;
	}
}

void CPGLAxe2D::DrawLinesGfx(gfxinterface::CGfxInterface& gfx)
{
	gfx.AddComment(_T("--- CPGLAxe2D: Drawing lines and ticks"));	

	if ( !m_lBoxTicks.IsVisible() || !m_lBoxTicks.IsInLayer(gfx.GetLayer()) )
		return;

	gfx.PushState();

	// setting no contour to BoxTicks
	m_lBoxTicks.SetContoured(false);

	// setting linewidth and line stipple
	m_lBoxTicks.CPGLObject::PlotGfx(gfx);
	gfx.SetLineWidth(m_lBoxTicks.GetLineWidth());	
	m_lBoxTicks.SetDashGfx(gfx);	

	gfx.DrawRect(m_pStarts[0], m_pStarts[1], m_pEnds[0], m_pEnds[1], m_lBoxTicks.GetERectType());

	if (m_rBorderLineVis.bottom)
		gfx.DrawLine(m_pStarts[0], m_pStarts[1], m_pEnds[0], m_pStarts[1]);
	if (m_rBorderLineVis.top)
		gfx.DrawLine(m_pStarts[0], m_pEnds[1], m_pEnds[0], m_pEnds[1]);
	if (m_rBorderLineVis.left)
		gfx.DrawLine(m_pStarts[0], m_pStarts[1], m_pStarts[0], m_pEnds[1]);
	if (m_rBorderLineVis.right)
		gfx.DrawLine(m_pEnds[0], m_pStarts[1], m_pEnds[0], m_pEnds[1]);

	double dPosTop = m_pNumberPos[ENumberingTop]*(m_pEnds[1]-m_pStarts[1]);
	double dPosBottom = m_pNumberPos[ENumberingBottom]*(m_pEnds[1]-m_pStarts[1]);
	double dPosLeft = m_pNumberPos[ENumberingLeft]*(m_pEnds[0]-m_pStarts[0]);
	double dPosRight = m_pNumberPos[ENumberingRight]*(m_pEnds[0]-m_pStarts[0]);

	// bottom
	if (m_pNumbers[ENumberingBottom].IsVisible() && m_pNumbers[ENumberingBottom].IsInLayer(gfx.GetLayer()))
		gfx.DrawLine(m_pStarts[0],  m_pStarts[1] + dPosBottom,m_pEnds[0], m_pStarts[1] + dPosBottom );

	//left
	if (m_pNumbers[ENumberingLeft].IsVisible() && m_pNumbers[ENumberingLeft].IsInLayer(gfx.GetLayer()))
		gfx.DrawLine( m_pStarts[0]+dPosLeft  , m_pStarts[1], m_pStarts[0]+ dPosLeft, m_pEnds[1]);

	//right
	if (m_pNumbers[ENumberingRight].IsVisible() && m_pNumbers[ENumberingRight].IsInLayer(gfx.GetLayer()))
		gfx.DrawLine(m_pStarts[0]+dPosRight  , m_pStarts[1], m_pStarts[0]+dPosRight , m_pEnds[1]);

	//top
	if (m_pNumbers[ENumberingTop].IsVisible() && m_pNumbers[ENumberingTop].IsInLayer(gfx.GetLayer()))
		gfx.DrawLine(m_pStarts[0], m_pStarts[1] +dPosTop, m_pEnds[0], m_pStarts[1] + dPosTop);


	// draw secondary ticks
	// bottom
	if (m_pSecondTicksNb[ETickBottom]>0 && m_pSecondTicksSize[ETickBottom])
		gfx.DrawGridVer(m_pStarts[0],m_pEnds[0],m_pStarts[1]+dPosBottom,m_pStarts[1]+dPosBottom+gfx.BBToWorldAbsy( m_pSecondTicksSize[ETickBottom] ),m_pSteps[0]/(m_pSecondTicksNb[0]+1) );

	//left
	if (m_pSecondTicksNb[ETickLeft]>0 && m_pSecondTicksSize[ETickLeft])
		gfx.DrawGridHor(m_pStarts[0]+dPosLeft,m_pStarts[0]+dPosLeft+gfx.BBToWorldAbsx( m_pSecondTicksSize[ETickLeft] ),m_pStarts[1],m_pEnds[1],m_pSteps[1]/(m_pSecondTicksNb[1]+1));

	//right
	if (m_pSecondTicksNb[ETickRight]>0 && m_pSecondTicksSize[ETickRight])
		gfx.DrawGridHor(m_pStarts[0]+dPosRight,m_pStarts[0]+dPosRight-gfx.BBToWorldAbsx( m_pSecondTicksSize[ETickRight] ),m_pStarts[1],m_pEnds[1],m_pSteps[1]/(m_pSecondTicksNb[2]+1));

	// top
	if (m_pSecondTicksNb[ETickTop]>0 && m_pSecondTicksSize[ETickTop])
		gfx.DrawGridVer(m_pStarts[0],m_pEnds[0],m_pStarts[1]+dPosTop,m_pStarts[1]+dPosTop-gfx.BBToWorldAbsy( m_pSecondTicksSize[ETickTop] ),m_pSteps[0]/(m_pSecondTicksNb[3]+1));

	// draw main ticks
	if ( m_pMainTicksSize[ETickBottom] )
		gfx.DrawGridVer(m_pStarts[0],m_pEnds[0],m_pStarts[1]+dPosBottom,m_pStarts[1]+dPosBottom+gfx.BBToWorldAbsy( m_pMainTicksSize[ETickBottom] ),m_pSteps[0]);
	if ( m_pMainTicksSize[ETickLeft])
		gfx.DrawGridHor(m_pStarts[0]+dPosLeft,m_pStarts[0]+dPosLeft+gfx.BBToWorldAbsx( m_pMainTicksSize[ETickLeft] ),m_pStarts[1],m_pEnds[1],m_pSteps[1]);
	if ( m_pMainTicksSize[ETickRight])
		gfx.DrawGridHor(m_pStarts[0]+dPosRight,m_pStarts[0]+dPosRight-gfx.BBToWorldAbsx( m_pMainTicksSize[ETickRight] ),m_pStarts[1],m_pEnds[1],m_pSteps[1]);
	if( m_pMainTicksSize[ETickTop])
		gfx.DrawGridVer(m_pStarts[0],m_pEnds[0],m_pStarts[1]+dPosTop,m_pStarts[1]+dPosTop-gfx.BBToWorldAbsy( m_pMainTicksSize[ETickTop] ),m_pSteps[0]);

	gfx.PopState();
}

void CPGLAxe2D::DrawNumbersGfx(gfxinterface::CGfxInterface& gfx)
{
	// choosing and setting font
	CString str;
	int maxStrLength[4]={0,0,0,0};
	COleDateTime curtime;
	COleDateTimeSpan dt;
	UINT nLabels,i;
	double nsec;
	UINT secnow; 
	double x,y,dygfx, dScale;
	int iScale;

	EstimateNumberingSize();

	// sending grid number to gfx...	
	// bottom
	if (m_pNumbers[ENumberingBottom].IsVisible() && m_pNumbers[ENumberingBottom].IsInLayer(gfx.GetLayer()) )
	{
		// creating vectors
		nLabels=(UINT)(floor) ((m_pEnds[0]-m_pStarts[0])/m_pSteps[0]+ 0.001)+1;
		std::vector<gfxinterface::SPointD> vPoints(nLabels);
		std::vector<std::_tstring> vStrings(nLabels);

		// getting scaling
		iScale = GetExponentScaling(m_pStarts[0], m_pEnds[0], m_pNumberExpLimits[0]);
		dScale = pow(10.0, iScale);

		// Creating strings...
		x=m_pStarts[0];
		y=m_pStarts[1] - gfx.BBToWorldAbsy( m_pNumbers[ENumberingBottom].GetPixelAnchorToTop() + 5 ) 
			+ m_pNumberPos[ENumberingBottom]*(m_pEnds[1] - m_pStarts[1]);
		for (i=0;i<nLabels;i++)
		{
			// checking x
			if (fabs(x) < m_pSteps[0]*1e-3)
				x=0;

			// first point
			if (m_bTimeLabel)
			{
				nsec = m_tsDt.GetTotalSeconds();
				secnow = (int)floor(x*nsec);
				dt=COleDateTimeSpan( secnow/(24*3600), 
					(secnow%(24*3600))/3600, 
					(secnow%3600)/60,
					secnow%60);
				curtime = m_tTimeLabelOrig+dt;
				str=curtime.Format(m_sTimeLabel);
			}
			else
			{
				str.Format(m_pNumbers[0].GetDescription(),x/dScale);
			}

			vPoints[i].x=x;
			vPoints[i].y=y;
			vStrings[i]=str;
			// updating x
			x+=m_pSteps[0];

			// updating maxstr
			maxStrLength[0]=__max(maxStrLength[0], str.GetLength());
		}

		// changing string if scaling present...
		if (iScale != 0 && !m_bTimeLabel)
		{
			str.Format(_T("x10^%d"), iScale);
			vPoints.resize(nLabels+1);
			vStrings.resize(nLabels+1);
			vPoints[nLabels].x = vPoints[nLabels-1].x - m_pSteps[0]/2.0;
			vPoints[nLabels].y = y;
			vStrings[nLabels] = str;
		}

		// Drawing...
		// setting font
		m_pNumbers[ENumberingBottom].GetFont().SetFontGfx(gfx);
		// setting color
		m_pNumbers[ENumberingBottom].CPGLObject::PlotGfx(gfx);
		// drawing
		gfx.DrawTextStrip(vPoints, vStrings,m_pNumbers[ENumberingBottom].GetAlign(), m_pNumbers[ENumberingBottom].GetAngle());
	}

	// left
	if (m_pNumbers[1].IsVisible() && m_pNumbers[1].IsInLayer(gfx.GetLayer()))
	{
		// creating vectors
		nLabels=(UINT)(floor) ((m_pEnds[1]-m_pStarts[1])/m_pSteps[1] + 0.001)+1;
		std::vector<gfxinterface::SPointD> vPoints(nLabels);
		std::vector<std::_tstring> vStrings(nLabels);
		
		// getting scaling
		iScale = GetExponentScaling(m_pStarts[1], m_pEnds[1], m_pNumberExpLimits[1]);
		dScale = pow(10.0, iScale);

		x=m_pStarts[0] - gfx.BBToWorldAbsx(5) + m_pNumberPos[1]*(m_pEnds[0] - m_pStarts[0]);
		y=m_pStarts[1];
		dygfx=gfx.BBToWorldAbsy(m_pNumbers[2].GetPixelAnchorToTop()/2);
		for (i=0;i<nLabels;i++)
		{
			// checking x
			if (fabs(y) < m_pSteps[1]*1e-3)
				y=0;
			// first point
			str.Format(m_pNumbers[1].GetDescription(),y/dScale);

			vPoints[i].x=x;
			vPoints[i].y=y-dygfx;
			vStrings[i]=str;
			// updating y
			y+=m_pSteps[1];

			maxStrLength[1]=__max(maxStrLength[1], str.GetLength());
		}

		// changing string if scaling present...
		if (iScale != 0)
		{
			str.Format(_T("x10^%d"), iScale);
			vPoints.resize(nLabels+1);
			vStrings.resize(nLabels+1);
			vPoints[nLabels].x = x;
			vPoints[nLabels].y = vPoints[nLabels-1].y - m_pSteps[1]/2.0;
			vStrings[nLabels] = str;
		}


		// setting font
		m_pNumbers[1].GetFont().SetFontGfx(gfx);
		// setting color
		m_pNumbers[1].CPGLObject::PlotGfx(gfx);
		gfx.DrawTextStrip(vPoints, vStrings, m_pNumbers[1].GetAlign(), m_pNumbers[1].GetAngle());
	}

	// sending grid number to gfx...	
	// right
	if (m_pNumbers[2].IsVisible() && m_pNumbers[2].IsInLayer(gfx.GetLayer()))
	{
		// creating vectors
		nLabels=(UINT)(floor) ((m_pEnds[1]-m_pStarts[1])/m_pSteps[1]+ 0.001)+1;
		std::vector<gfxinterface::SPointD> vPoints(nLabels);
		std::vector<std::_tstring> vStrings(nLabels);

		// getting scaling
		iScale = GetExponentScaling(m_pStarts[1], m_pEnds[1], m_pNumberExpLimits[1]);
		dScale = pow(10.0, iScale);

		x=m_pStarts[0] + gfx.BBToWorldAbsx(5) + m_pNumberPos[2]*(m_pEnds[0] - m_pStarts[0]);
		y=m_pStarts[1];
		dygfx=gfx.BBToWorldAbsy(m_pNumbers[2].GetPixelAnchorToTop()/2);
		for (i=0;i<nLabels;i++)
		{
			// checking x
			if (fabs(y) < m_pSteps[1]*1e-3)
				y=0;
			// first point
			str.Format(m_pNumbers[2].GetDescription(),y/dScale);

			vPoints[i].x=x;
			vPoints[i].y=y-dygfx;
			vStrings[i]=str;
			// updating y
			y+=m_pSteps[1];

			maxStrLength[2]=__max(maxStrLength[2], str.GetLength());
		}


		// changing string if scaling present...
		if (iScale != 0)
		{
			str.Format(_T("x10^%d"), iScale);
			vPoints.resize(nLabels+1);
			vStrings.resize(nLabels+1);
			vPoints[nLabels].x = x;
			vPoints[nLabels].y = vPoints[nLabels-1].y - m_pSteps[1]/2.0;
			vStrings[nLabels] = str;
		}

		// setting font
		m_pNumbers[2].GetFont().SetFontGfx(gfx);
		// setting color
		m_pNumbers[2].CPGLObject::PlotGfx(gfx);
		// Drawing...
		gfx.DrawTextStrip(vPoints, vStrings, m_pNumbers[2].GetAlign(), m_pNumbers[2].GetAngle());
	}

	// top
	if (m_pNumbers[3].IsVisible() && m_pNumbers[3].IsInLayer(gfx.GetLayer()))
	{
		// creating vectors
		nLabels=(UINT)(floor) ((m_pEnds[0]-m_pStarts[0])/m_pSteps[0]+ 0.001)+1;
		std::vector<gfxinterface::SPointD> vPoints(nLabels);
		std::vector<std::_tstring> vStrings(nLabels);

		// getting scaling
		iScale = GetExponentScaling(m_pStarts[0], m_pEnds[0], m_pNumberExpLimits[0]);
		dScale = pow(10.0, iScale);

		// setting font
		m_pNumbers[3].GetFont().SetFontGfx(gfx);
		// setting color
		m_pNumbers[3].CPGLObject::PlotGfx(gfx);

		x=m_pStarts[0];
		y=m_pStarts[1]  +gfx.BBToWorldAbsy(5) + m_pNumberPos[3]*(m_pEnds[1] - m_pStarts[1]);
		for (i=0;i<nLabels;i++)
		{
			// checking x
			if (fabs(x) < m_pSteps[0]*1e-3)
				x=0;

			if (m_bTimeLabel)
			{
				nsec = m_tsDt.GetTotalSeconds();
				secnow = (int)floor(x*nsec);
				dt=COleDateTimeSpan( secnow/(24*3600), 
					(secnow%(24*3600))/3600, 
					(secnow%3600)/60,
					secnow%60);
				curtime = m_tTimeLabelOrig+dt;
				str=curtime.Format(m_sTimeLabel);

			}
			else
			{
				str.Format(m_pNumbers[3].GetDescription(),x/dScale);
			}

			vPoints[i].x=x;
			vPoints[i].y=y;
			vStrings[i]=str;

			// updating x
			x+=m_pSteps[0];
			maxStrLength[3]=__max(maxStrLength[3], str.GetLength());
		}

		// changing string if scaling present...
		if (iScale != 0 && !m_bTimeLabel)
		{
			str.Format(_T("x10^%d"), iScale);
			vPoints.resize(nLabels+1);
			vStrings.resize(nLabels+1);
			vPoints[nLabels].x = vPoints[nLabels-1].x - m_pSteps[0]/2.0;
			vPoints[nLabels].y = y;
			vStrings[nLabels] = str;
		}

		// setting font
		m_pNumbers[3].GetFont().SetFontGfx(gfx);
		// setting color
		m_pNumbers[3].CPGLObject::PlotGfx(gfx);
		gfx.DrawTextStrip(vPoints, vStrings, m_pNumbers[3].GetAlign(), m_pNumbers[3].GetAngle());

	}

	// setting number size
	for (i=0;i<4;i++)
	{
		std::_tstring stlStr;
		stlStr.insert(stlStr.begin(), maxStrLength[i], '0');	
		m_pNumbers[i].SetString(stlStr.c_str());
	}	

	UpdateLabels(gfx);

	// drawing labels...
	for (i=0;i<4;i++)
	{
		// writing down text...
		m_pLabels[i].PlotGfx(gfx);
	}
}

void CPGLAxe2D::DrawGridGfx(EAxis eAxe, gfxinterface::CGfxInterface& gfx)
{
	gfx.PushState();
	switch(eAxe)
	{
	case AxisVertical:
		m_lVerGrid.MakeFrontColorCurrent(gfx);
		m_lVerGrid.SetDashGfx(gfx);	
		gfx.SetLineWidth(m_lVerGrid.GetLineWidth());	
		gfx.DrawGridVer(m_pStarts[0],m_pEnds[0],m_pStarts[1],m_pEnds[1],m_pSteps[0]);
		break;
	case AxisHorizontal:
		m_lHorGrid.MakeFrontColorCurrent(gfx);
		m_lHorGrid.SetDashGfx(gfx);	
		gfx.SetLineWidth(m_lHorGrid.GetLineWidth());	
		gfx.DrawGridHor(m_pStarts[0],m_pEnds[0],m_pStarts[1],m_pEnds[1],m_pSteps[1]);
		break;
	}
	gfx.PopState();
}

void CPGLAxe2D::UpdateLabels(gfxinterface::CGfxInterface& gfx)
{
	using namespace gfxinterface;
   
	EstimateNumberingSize();

	for (UINT i=0;i<4;i++)
	{
		m_pLabels[i].UpdateExtent(gfx);
		m_pNumbers[i].UpdateExtent(gfx);
	}

	// bottom
	{
		CPGLCoord2D& pos=m_pLabels[ELabelBottom].GetPosition();
		pos.SetBBTrans( SPointD(0,m_pLabels[ELabelBottom].GetPixelAnchorToBottom()+5));	
	}

	// left
	{
		CPGLCoord2D& pos=m_pLabels[ELabelLeft].GetPosition();	
		pos.SetBBTrans(SPointD(m_pLabels[ELabelLeft].GetPixelAnchorToLeft()+5, 0 ));	
	}

	// right 
	{
		CPGLCoord2D& pos=m_pLabels[ELabelRight].GetPosition();
		pos.SetBBTrans( SPointD( -m_pLabels[ELabelRight].GetPixelAnchorToRight()-5, 0 ));	
	}

	// top
	{
		CPGLCoord2D& pos=m_pLabels[ELabelTop].GetPosition();
		pos.SetBBTrans( SPointD(0, -m_pLabels[ELabelTop].GetPixelAnchorToTop()-5 ));	
	}

}

void CPGLAxe2D::Pan(double dx, double dy)
{
	m_pStarts[0]+=dx;
	m_pEnds[0]+=dx;
	m_pStarts[1]+=dy;
	m_pEnds[1]+=dy;
}

void CPGLAxe2D::ZoomScale(double x, double y)
{
	double w=m_pEnds[0]-m_pStarts[0];
	double h=m_pEnds[1]-m_pStarts[1];

	m_pStarts[0]-=(x-1)*w/2.0;
	m_pEnds[0]+=(x-1)*w/2.0;
	m_pEnds[1]+=(y-1)*h/2.0;
	m_pStarts[1]-=(y-1)*h/2.0;
}

void CPGLAxe2D::ClipGfx(gfxinterface::CGfxInterface& gfx)
{
	GFX_ADDCOMMENT(gfx,"Axe2D: Clipping inside axis");
	gfx.PushClipWorld(m_pStarts[0],m_pStarts[1],m_pEnds[0],m_pEnds[1]);
}

void CPGLAxe2D::UnClipGfx(gfxinterface::CGfxInterface& gfx)
{
	GFX_ADDCOMMENT(gfx,"Axe2D: Unclipping");
	gfx.PopClipWorld();
}


void CPGLAxe2D::AddPropertyPage(CPropertySheet *pPropSheet)
{
	ASSERT_VALID(pPropSheet);

	// call own functions
	CPGLAxe2DPropPage* propPage=new CPGLAxe2DPropPage(this);
	pPropSheet->AddPage(propPage);

	// first call base class function
	CPGLObject::AddPropertyPage(pPropSheet);
}

HTREEITEM CPGLAxe2D::AddPropTree(CTreeCtrl* pTree, HTREEITEM hParent)
{
	int i;
	ASSERT_VALID(pTree);
	CImageList* pImgList=pTree->GetImageList(TVSIL_NORMAL);
	ASSERT_VALID(pImgList);
	ASSERT(hParent);
	COLORREF crMask=0;
	// adding bitmap
	pImgList->Add(CBitmap::FromHandle(GetBitmap()),crMask);
	// adding to tree
	HTREEITEM htAxe;
	htAxe=pTree->InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_PARAM  /* nMask*/, 
				GetName() /* lpszItem*/, 
				pImgList->GetImageCount()-1 /* nImage */, 
				0 /* nSelectedImage */, 
				0 /* nState */, 
				0 /* nStateMask */, 
				GetID() /*  lParam */, 
				hParent /* hParent */, 
				TVI_LAST /* hInsertAfter */);
	ASSERT(htAxe!=NULL);

	// adding title and labels
	HTREEITEM htLabels;
	htLabels=pTree->InsertItem(TVIF_TEXT | TVIF_IMAGE /* nMask*/, 
				_T("Labels") /* lpszItem*/, 
				pImgList->GetImageCount()-1 /* nImage */, 
				0 /* nSelectedImage */, 
				0 /* nState */, 
				0 /* nStateMask */, 
				-1 /*  lParam */, 
				htAxe /* hParent */, 
				TVI_LAST /* hInsertAfter */);
	ASSERT(htLabels!=NULL);
	for (i=0;i<4;i++)
	{
		m_pLabels[i].AddPropTree(pTree,htLabels);
	}

	// adding numbers
	HTREEITEM htNumbers;
	htNumbers=pTree->InsertItem(TVIF_TEXT | TVIF_IMAGE /* nMask*/, 
				_T("Numbering") /* lpszItem*/, 
				pImgList->GetImageCount()-1 /* nImage */, 
				0 /* nSelectedImage */, 
				0 /* nState */, 
				0 /* nStateMask */, 
				-1 /*  lParam */, 
				htAxe /* hParent */, 
				TVI_LAST /* hInsertAfter */);
	ASSERT(htNumbers!=NULL);
	for (i=0;i<4;i++)
	{
		m_pNumbers[i].AddPropTree(pTree,htNumbers);
	}

	// adding Grids
	HTREEITEM htGrids;
	htGrids=pTree->InsertItem(TVIF_TEXT | TVIF_IMAGE /* nMask*/, 
				_T("Grids") /* lpszItem*/, 
				pImgList->GetImageCount()-1 /* nImage */, 
				0 /* nSelectedImage */, 
				0 /* nState */, 
				0 /* nStateMask */, 
				-1 /*  lParam */, 
				htAxe /* hParent */, 
				TVI_LAST /* hInsertAfter */);
	ASSERT(htNumbers!=NULL);
	m_lHorGrid.AddPropTree(pTree,htGrids);
	m_lVerGrid.AddPropTree(pTree,htGrids);

	return htAxe;
}

/*
CPGLObject* CPGLAxe2D::FindObjectID(UINT ID)
{

	// check if it is title
	for (int i=0;i<4;i++)
	{
		if (m_pLabels[i].CheckID(ID))
			return &m_pLabels[i];
	}

	// check if it is numbering
	for (i=0;i<4;i++)
	{
		if (m_pNumbers[i].CheckID(ID))
			return &m_pNumbers[i];
	}

	if (m_lHorGrid.CheckID(ID))
		return &m_lHorGrid;
	if (m_lVerGrid.CheckID(ID))
		return &m_lVerGrid;

	// none return NULL
	return CPGLObject::FindObjectID(ID);
}
*/

void CPGLAxe2D::SetTimeLabelFormat(const COleDateTime& _otOrig, const COleDateTimeSpan& _otsDt, LPCTSTR _szTimeLabel)
{	
	m_tTimeLabelOrig = _otOrig; 
	m_tsDt = _otsDt; 
	m_sTimeLabel = _szTimeLabel;
};

void CPGLAxe2D::SetTimeLabelFormat(const CTime& _tOrig, const CTimeSpan& _tsDt, LPCTSTR _szTimeLabel)
{
	COleDateTime _otOrig( _tOrig.GetYear(),
		_tOrig.GetMonth(),
		_tOrig.GetDay(),
		_tOrig.GetHour(),
		_tOrig.GetMinute(),
		_tOrig.GetSecond());

	COleDateTimeSpan _otsDt((long)_tsDt.GetDays(),
		(long)_tsDt.GetHours(),
		(long)_tsDt.GetMinutes(),
		(long)_tsDt.GetSeconds());

	SetTimeLabelFormat(_otOrig, _otsDt, _szTimeLabel);
}


void CPGLAxe2D::GrowExtent(CPGLRectD& rExt, const CPGLRectD* pOutsideBorders, const CPGLRectD* pInsideBorders)
{
	ASSERT_VALID(m_pView);

	///////////////////////////////////////////////////////////////////////////////////////////////
	// getting screen size (in pixels)
	int iW=m_pView->GetWidth();
	int iH=m_pView->GetHeight();

	if (!IsVisible())
	{
		m_rBorders=CPGLRectD(5,5,5,5);
	}
	else
	{
		// initialize borders
		if (pInsideBorders)
		{
			if (m_rAutoBorders.left)
				m_rBorders.left=pInsideBorders->left;
			if (m_rAutoBorders.right)
				m_rBorders.right=pInsideBorders->right;
			if (m_rAutoBorders.top)
				m_rBorders.top=pInsideBorders->top;
			if (m_rAutoBorders.bottom)
				m_rBorders.bottom=pInsideBorders->bottom;
		}
		else
		{
			if (m_rAutoBorders.left)
				m_rBorders.left=10;
			if (m_rAutoBorders.right)
				m_rBorders.right=10;
			if (m_rAutoBorders.top)
				m_rBorders.top=10;
			if (m_rAutoBorders.bottom)
				m_rBorders.bottom=10;
		}
	
		//////////////////////////////////////////////////////////////////////////////////////////////
		// Compute optimal borders...
		// left
		if (m_rAutoBorders.left)
		{
	
			if ( GetLeftLabel().IsVisible() )
				m_rBorders.left+= GetLeftLabel().GetPixelWidth(); 
			if ( GetLeftNumber().IsVisible() )
				m_rBorders.left+= GetLeftNumber().GetPixelWidth()+5;
		}

		// right
		if (m_rAutoBorders.right)
		{
			if ( GetRightLabel().IsVisible() )
				m_rBorders.right+= GetRightLabel().GetPixelWidth(); 
			if ( GetRightNumber().IsVisible())
				m_rBorders.right+= GetRightNumber().GetPixelWidth()+5;
		}
	
		// bottom
		if (m_rAutoBorders.bottom)
		{
			if ( GetBottomLabel().IsVisible())
				m_rBorders.bottom+= GetBottomLabel().GetPixelHeight(); 
			if ( GetBottomNumber().IsVisible() )
				m_rBorders.bottom+= GetBottomNumber().GetPixelHeight();
		}
		
		// top
		if (m_rAutoBorders.top)
		{
			if ( GetTopLabel().IsVisible())
				m_rBorders.top+= GetTopLabel().GetPixelHeight(); 
			if ( GetTopNumber().IsVisible() )
				m_rBorders.top+= GetTopNumber().GetPixelHeight();
		}
	}

	if (pOutsideBorders)
	{
		m_rBorders.left+=pOutsideBorders->left;
		m_rBorders.right+=pOutsideBorders->right;
		m_rBorders.bottom+=pOutsideBorders->bottom;
		m_rBorders.top+=pOutsideBorders->top;
	}

	/////////////////////////////////////////////////////////////////////////////////////////////
	// Horizontal scaling
	// we want to have iAxeLeft pixels on the left and iAxeRight pixels on the right...
	int iWPlot=__max(1,(int)floor(iW-m_rBorders.left-m_rBorders.right));	// pixels left to draw data
	double dWScale=(rExt.GetWidth())/iWPlot;

	// updating extent
	rExt.left-=m_rBorders.left*dWScale;
	rExt.right+=m_rBorders.right*dWScale;

	/////////////////////////////////////////////////////////////////////////////////////////////
	// Vertical scaling
	int iHPlot=__max(1,(int)floor(iH-m_rBorders.bottom-m_rBorders.top));	// pixels left to draw data
	double dHScale=(rExt.GetHeight())/iHPlot;

	// updating extent
	rExt.bottom-=m_rBorders.bottom*dHScale;
	rExt.top+=m_rBorders.top*dHScale;

	if (pOutsideBorders)
	{
		m_rBorders.left-=pOutsideBorders->left;
		m_rBorders.right-=pOutsideBorders->right;
		m_rBorders.bottom-=pOutsideBorders->bottom;
		m_rBorders.top-=pOutsideBorders->top;
	}
}

void CPGLAxe2D::EstimateNumberingSize()
{
	int maxStrLength;
	CString str;
	double x,y;
	COleDateTime curtime;
	COleDateTimeSpan dt;
	double nsec;
	UINT secnow; 

	///////////////////////////////////////////////////////////
	// left
	y=m_pStarts[1];
	// checking x
	if (fabs(y) < m_pSteps[1]*1e-3)
		y=0;
	// first point
	str.Format(m_pNumbers[1].GetDescription(),y);
	maxStrLength=str.GetLength();
		
	y=m_pStarts[1]+m_pSteps[1];
	// checking x
	if (fabs(y) < m_pSteps[1]*1e-3)
		y=0;
	// first point
	str.Format(m_pNumbers[1].GetDescription(),y);
	maxStrLength=__max(maxStrLength,str.GetLength());
		
	y=m_pEnds[1];
	// checking x
	if (fabs(y) < m_pSteps[1]*1e-3)
		y=0;

	// first point
	str.Format(m_pNumbers[1].GetDescription(),y);
	maxStrLength=__max(maxStrLength,str.GetLength());

	std::_tstring stlStr;
	stlStr.insert(stlStr.begin(), maxStrLength, '0');	
	m_pNumbers[1].SetString(stlStr.c_str());

	///////////////////////////////////////////////////////////
	// right
	y=m_pStarts[1];
	// checking x
	if (fabs(y) < m_pSteps[1]*1e-3)
		y=0;
	// first point
	str.Format(m_pNumbers[2].GetDescription(),y);
	maxStrLength=str.GetLength();
		
	y=m_pStarts[1]+m_pSteps[1];
	// checking x
	if (fabs(y) < m_pSteps[1]*1e-3)
		y=0;
	// first point
	str.Format(m_pNumbers[2].GetDescription(),y);
	maxStrLength=__max(maxStrLength,str.GetLength());
		
	// end point
	y=m_pEnds[1];
	// checking x
	if (fabs(y) < m_pSteps[1]*1e-3)
		y=0;
	str.Format(m_pNumbers[2].GetDescription(),y);
	maxStrLength=__max(maxStrLength,str.GetLength());

	stlStr.insert(stlStr.begin(), maxStrLength, '0');	
	m_pNumbers[2].SetString(stlStr.c_str());

	////////////////////////////////////////////////////////////////////////////
	// bottom
	// creating vectors
	x=m_pStarts[0];
	// checking x
	if (fabs(x) < m_pSteps[0]*1e-3)
		x=0;
	if (m_bTimeLabel)
	{
		nsec = m_tsDt.GetTotalSeconds();
		secnow = (int)floor(x*nsec);
		dt=COleDateTimeSpan( secnow/(24*3600), 
			(secnow%(24*3600))/3600, 
			(secnow%3600)/60,
			secnow%60);
		curtime = m_tTimeLabelOrig+dt;
		str=curtime.Format(m_sTimeLabel);

	}
	else
	{
		str.Format(m_pNumbers[0].GetDescription(),x);
	}
	maxStrLength=str.GetLength();

	// creating vectors
	x=m_pStarts[0]+ m_pSteps[0];
	// checking x
	if (fabs(x) < m_pSteps[0]*1e-3)
		x=0;
	if (m_bTimeLabel)
	{
		nsec = m_tsDt.GetTotalSeconds();
		secnow = (int)floor(x*nsec);
		dt=COleDateTimeSpan( secnow/(24*3600), 
			(secnow%(24*3600))/3600, 
			(secnow%3600)/60,
			secnow%60);
		curtime = m_tTimeLabelOrig+dt;
		str=curtime.Format(m_sTimeLabel);
		}
	else
	{
		str.Format(m_pNumbers[0].GetDescription(),x);
	}
	maxStrLength=__max( maxStrLength,str.GetLength());
	// creating vectors
	x=m_pEnds[0];
	// checking x
	if (fabs(x) < m_pSteps[0]*1e-3)
		x=0;
	if (m_bTimeLabel)
	{
		nsec = m_tsDt.GetTotalSeconds();
		secnow = (int)floor(x*nsec);
		dt=COleDateTimeSpan( secnow/(24*3600), 
			(secnow%(24*3600))/3600, 
			(secnow%3600)/60,
			secnow%60);
		curtime = m_tTimeLabelOrig+dt;
		str=curtime.Format(m_sTimeLabel);
	}
	else
	{
		str.Format(m_pNumbers[0].GetDescription(),x);
	}
	maxStrLength=__max( maxStrLength,str.GetLength());

	stlStr=_T("");
	stlStr.insert(stlStr.begin(), maxStrLength, '0');	
	m_pNumbers[0].SetString(stlStr.c_str());


	////////////////////////////////////////////////////////////////////////////
	// top
	// creating vectors
	x=m_pStarts[0];
	// checking x
	if (fabs(x) < m_pSteps[0]*1e-3)
		x=0;
	if (m_bTimeLabel)
	{
		nsec = m_tsDt.GetTotalSeconds();
		secnow = (int)floor(x*nsec);
		dt=COleDateTimeSpan( secnow/(24*3600), 
			(secnow%(24*3600))/3600, 
			(secnow%3600)/60,
			secnow%60);
		curtime = m_tTimeLabelOrig+dt;
		str=curtime.Format(m_sTimeLabel);

	}
	else
	{
		str.Format(m_pNumbers[3].GetDescription(),x);
	}
	maxStrLength=str.GetLength();

	// creating vectors
	x=m_pStarts[0]+ m_pSteps[0];
	// checking x
	if (fabs(x) < m_pSteps[0]*1e-3)
		x=0;
	if (m_bTimeLabel)
	{
		nsec = m_tsDt.GetTotalSeconds();
		secnow = (int)floor(x*nsec);
		dt=COleDateTimeSpan( secnow/(24*3600), 
			(secnow%(24*3600))/3600, 
			(secnow%3600)/60,
			secnow%60);
		curtime = m_tTimeLabelOrig+dt;
		str=curtime.Format(m_sTimeLabel);
		}
	else
	{
		str.Format(m_pNumbers[3].GetDescription(),x);
	}
	maxStrLength=__max( maxStrLength,str.GetLength());
	// creating vectors
	x=m_pEnds[0];
	// checking x
	if (fabs(x) < m_pSteps[0]*1e-3)
		x=0;
	if (m_bTimeLabel)
	{
		nsec = m_tsDt.GetTotalSeconds();
		secnow = (int)floor(x*nsec);
		dt=COleDateTimeSpan( secnow/(24*3600), 
			(secnow%(24*3600))/3600, 
			(secnow%3600)/60,
			secnow%60);
		curtime = m_tTimeLabelOrig+dt;
		str=curtime.Format(m_sTimeLabel);
	}
	else
	{
		str.Format(m_pNumbers[3].GetDescription(),x);
	}
	maxStrLength=__max( maxStrLength,str.GetLength());

	stlStr=_T("");
	stlStr.insert(stlStr.begin(), maxStrLength, '0');	
	m_pNumbers[3].SetString(stlStr.c_str());
}

int CPGLAxe2D::GetExponentScaling( double dStart, double dEnd, double dExpLimit)
{
	double dScale;
	double eStart, eEnd;

	dScale=0;
	eStart=log10(fabs(dStart));
	eEnd=log10(fabs(dEnd)) ;

	if (dEnd >0)
	{
		if ( fabs( eEnd ) > dExpLimit )
			dScale=eEnd/dExpLimit;
	}
	else
	{
		if ( fabs( eStart ) > dExpLimit )
			dScale=(eStart)/dExpLimit-1;
	}

/*	// checking if rescaling is needed...
	if ( fabs( log10( fabs(dEnd) )) > dExpLimit )
	{
		dScale = __max(dScale, ( floor(fabs( log10( fabs(dEnd))) / dExpLimit) )*dExpLimit );
	}

	if ( fabs(log10( fabs(dStart) )) > dExpLimit )
	{
		dScale = __max(dScale, ( ceil(fabs( log10( fabs(dStart)) ) / dExpLimit) )*dExpLimit);
	}
*/
	return (int)floor(floor(dScale)*dExpLimit);
}

void CPGLAxe2D::SetLabel(ELabelIndex eLabel, const CPGLText& newLabel)
{	
	CPGLCoord2D pos=m_pLabels[eLabel].GetPosition(); 
	float angle = m_pLabels[eLabel].GetAngle();
	
	m_pLabels[eLabel]=newLabel; 
	m_pLabels[eLabel].SetPosition(pos);
	m_pLabels[eLabel].SetAngle(angle);
};
